﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using Raider.WinForms.Actions.Properties;
using System.Threading;
using System.Drawing;

namespace Raider.WinForms.Actions.Standard
{
    /// <summary>
    /// Base class for all actions that use the common dialogs.
    /// </summary>
    [DefaultProperty("Dialog"), DefaultEvent("Accept"), HideEvent("Execute")]
    public abstract class CommonDialogAction<TDialog> : StandardAction where TDialog : CommonDialog, new()
    {
        private readonly TDialog dialog = new TDialog();
        private DialogResult dialogResult;

        /// <summary>
        /// Initializes a new instance of the <see cref="CommonDialogAction"/>.
        /// </summary>
        /// <param name="title">Default title for the action (empty by default).</param>
        /// <param name="category">Default category for the action (empty by default).</param>
        /// <param name="shortcut">Default shortcut for the action (none by default).</param>
        /// <param name="image">Default image for the action (<c>null</c> by default).</param>
        protected CommonDialogAction(string title = "", string category = "", Keys shortcut = Keys.None, Image image = null)
            : base(title, category, shortcut, image)
        {
        }

        /// <summary>
        /// Dialog used by the action.
        /// </summary>
        [Category("Behavior"), Description("Dialog used by the action.")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public TDialog Dialog
        {
            get { return dialog; }
        }

        protected override void OnExecuting(ExecutingEventArgs args)
        {
            base.OnExecuting(args);

            if (args != null && !args.Cancel)
            {
                dialogResult = dialog.ShowDialog();
            }
        }

        protected override void OnExecute(ExecuteEventArgs args)
        {
            base.OnExecute(args);

            if (dialogResult == DialogResult.OK)
            {
                OnAccept(args);
            }
            else
            {
                OnCancel(args);
            }
        }

        #region Events

        /// <summary>
        /// Occurs when user accepts the dialog.
        /// </summary>
        [Category("Behavior"), Description("Occurs when user clicks OK in the dialog.")]
        public event EventHandler Accept;

        /// <summary>
        /// Occurs when user cancels the dialog.
        /// </summary>
        [Category("Behavior"), Description("Occurs when user cancels the dialog.")]
        public event EventHandler Cancel;

        protected virtual void OnAccept(EventArgs args)
        {
            var handler = Accept;
            if (handler != null) handler(this, args);
        }

        protected virtual void OnCancel(EventArgs args)
        {
            var handler = Cancel;
            if (handler != null) handler(this, args);
        }

        #endregion

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                dialog.Dispose();
            }

            base.Dispose(disposing);
        }
    }
}
